💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    로딩 중이에요... 🐣

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    19 데이터 충돌 및 중복 처리 | ✅ 저자: 이유정(박사)

    데이터 중복이 왜 문제인가요?

    1. “하나만 있어야 할 정보”가 여러 번 나타나면

      • 예를 들어 주문 번호나 회원 아이디처럼 고유해야 할 값이 중복되면, 실제로는 하나의 주문이나 한 명의 회원인 것을 두 번 이상 셈하게 됩니다.
      • 이렇게 되면 “총 몇 건의 주문이 들어왔나요?” 같은 간단한 집계 결과도 실제보다 크게 나와서, 잘못된 의사결정을 내릴 수 있습니다.
    2. 사용자 정보에 오류(중복)가 있으면 활동이 과장될 수 있습니다

      • 같은 사람이 가입만 여러 번 했다고 보면, “활동 유저 수”나 “구매 고객 수”가 실제보다 많아집니다.
      • 예를 들어 고객 A가 실제로 1번만 구매했는데, 데이터가 중복되어 A가 3명처럼 보이면 “3번 구매한 고객이 있다”는 식으로 잘못 해석될 수 있습니다.

    쉽게 생각해 보기

    • 도서관 책 대출 기록을 관리하는데, 같은 책이 두 번 대출된 기록이 남아 있다면 “책을 두 번 대출했나?” 하고 헷갈리는 것과 같습니다.

    • 운동 기록 앱에서 A 사용자가 한 번만 달리기를 했는데, 기록이 중복 저장돼 A가 두 번 달리기를 한 것처럼 보이면, 통계가 틀어집니다.

    결국 원본 데이터의 고유성(unique) 이 깨지면, 그 데이터를 바탕으로 하는 모든 분석·보고·의사결정이 잘못될 위험이 커집니다.

    import pandas as pd
    
    # CSV 파일 불러오기
    df = pd.read_csv("csv_files/combined_customers.csv")
    
    # 처음 10줄 미리 보기
    print("-----처음 10줄 미리 보기--------")
    print(df.head(10))
    
    # 중복된 customer_id 찾기 (첫 번째 항목을 남기고 나머지를 중복으로 판단)
    duplicates = df.duplicated(subset='customer_id', keep='first')
    
    # 중복된 행 출력 (== 제거될 행들)
    removed_rows = df[duplicates]
    print("\n-----제거될 행들-----")
    print(removed_rows)
    
    # 중복 제거
    df_cleaned = df.drop_duplicates(subset='customer_id', keep='first')
    
    # 결과 출력
    print("\n-----중복 제거 후 데이터 수-----")
    print(f"원래 데이터 수: {len(df)}")
    print(f"중복 제거 후 데이터 수: {len(df_cleaned)}")
    
    # 중복 제거 후 미리 보기
    print("\n-----중복 제거된 데이터 미리 보기 (상위 10줄)-----")
    print(df_cleaned.head(10))
    

    pandas에서 중복된 데이터를 찾기 위한 핵심 코드

    duplicates = df.duplicated(subset='customer_id', keep='first')
    

    df.duplicated(...)

    • pandasduplicated() 함수는
      데이터프레임에서 중복된 행을 찾을 때 사용하는 함수입니다.
    • 이 함수는 각 줄(행)이 중복인지 아닌지를 판단해서 True/False로 알려줘요.

    subset='customer_id'

    • 중복을 판단할 때 어떤 컬럼(열)을 기준으로 할지 정하는 거예요
    • 고객 정보가 담긴 표에서 customer_id를 기준으로 같은 ID가 여러 번 나오는지 확인합니다.

    keep='first'

    • 중복된 값들 중에서 첫 번째는 남기고(True안줌) 나머지는 중복(True)로 표시하라는 뜻입니다. 상황예시:
    index  customer_id  name
    0       1           Eunice
    1       2           Bob
    3       3           Aice
    4       1           Eunice
    5       2           Bob
    

    결과:

    0       False       # customer_id=1 → 첫 번째니까 중복 아님
    1       False       # customer_id=2 → 첫 번째니까 중복 아님
    2       False       # customer_id=1 → 첫 번째니까 중복 아님
    3       True        # customer_id=3 → 두 번째 나왔으니 중복
    4       True        # customer_id=2 → 두 번째 나왔으니 중복
    

    실습 문제: 중복된 고객 데이터 처리하기 목표:

    • 고객 ID가 같은 행들 중에서 이메일이 서로 다른 경우를 식별합니다.
    • 이처럼 ID는 같은데 이메일이 다른 경우는 데이터 충돌로 간주하고 따로 추출해야 합니다.
    • 또한 ID와 이메일이 둘 다 같은 경우는 진짜 중복이므로 제거합니다.

    [문제 배경] 고객 데이터 병합 중에 customer_id가 같은데, 이메일 정보가 서로 다른 경우가 발견되었습니다.
    이는 고객 ID 중복으로 인해 발생한 데이터 충돌 사례입니다.
    반면, ID와 이메일이 모두 같으면 단순 중복일 수 있으므로, 그건 제거 대상입니다.

    업무 요청사항:

    • 고객 ID 기준으로 이메일이 서로 다른 경우를 찾아서 따로 분리합니다.
    • 나머지 데이터 중에서, ID와 이메일이 모두 같은 경우는 1개만 남기고 중복 제거합니다.
    • 충돌 데이터 수와 일반 중복 제거 후 데이터 수를 출력합니다.
    • 충돌 데이터는 따로 conflict_df, 정제된 데이터는 cleaned_df로 저장하여 출력합니다.

    해야 할 작업 순서

    • combined_customers.csv 파일을 읽어서 df로 저장합니다.
    • customer_id별로 이메일이 서로 다른 행이 있는 경우만 따로 뽑아 conflict_df로 저장합니다.
    • 위에서 뽑힌 충돌 데이터를 제외한 나머지에서 ID+이메일 기준으로 중복 제거합니다.
    • conflict_df, cleaned_df 각각의 크기와 상위 5행을 출력합니다.

    정답코드

    import pandas as pd
    
    # 1. 데이터 불러오기
    df = pd.read_csv("csv_files/combined_customers.csv")
    
    # 2. 이메일 충돌 확인: 같은 ID인데 이메일이 다른 경우
    email_counts = df.groupby('customer_id')['email'].nunique()
    conflict_ids = email_counts[email_counts > 1].index
    
    # 3. 충돌 데이터만 따로 추출
    conflict_df = df[df['customer_id'].isin(conflict_ids)]
    
    # 4. 충돌 데이터 제외
    df_remaining = df[~df['customer_id'].isin(conflict_ids)]
    # ~는 Pandas에서 "not", 즉 부정(반대)을 의미하는 논리 연산자입니다.
    # ~는 이 결과를 반대로 뒤집는 연산자입니다.
    
    # 5. 남은 데이터에서 ID + 이메일 기준으로 중복 제거
    cleaned_df = df_remaining.drop_duplicates(subset=['customer_id', 'email'], keep='first')
    
    # 6. 결과 출력
    print(f"충돌 고객 수: {conflict_df['customer_id'].nunique()}명")
    print(f"정제된 고객 수: {cleaned_df['customer_id'].nunique()}명")
    print("\n충돌된 데이터 일부:")
    print(conflict_df.head())
    
    print("\n정제된 데이터 일부:")
    print(cleaned_df.head())
    
    TOP
    preload preload